package retrofit.boot.converter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import retrofit.boot.exception.RetrofitClientConvertionException;
import retrofit.converter.ConversionException;
import retrofit.converter.Converter;
import retrofit.mime.TypedInput;
import retrofit.mime.TypedOutput;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;

/**
 * Created by wulg on 2019/10/22
 * description:服务暴露点配置接口
 */
@Slf4j
public class FastjsonConverter implements Converter {
    private String charset;

    public FastjsonConverter() {
        this("UTF-8");
    }
    public FastjsonConverter(String charset) {
        this.charset = charset;
    }

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
        String bodyStr = null;
        try {
            bodyStr = IOUtils.toString(body.in(), charset);
            if (type == String.class) {
                return bodyStr;
            } else {
                return JSON.parseObject(bodyStr,type);
            }
        } catch (JSONException  | IOException e) {
            log.error(e.getMessage(),e);
            throw new ConversionException(e);
        }
    }

    @Override
    public TypedOutput toBody(Object object) {
        try {
            String json;
            if (object instanceof String) {
                json = object.toString();
            } else {
                json = JSON.toJSONString(object);
            }
            return new JsonTypedOutput(json.getBytes(charset), charset);
        } catch (JSONException | UnsupportedEncodingException e) {
            log.error(e.getMessage(),e);
            throw new RetrofitClientConvertionException(e);
        }
    }

    private static class JsonTypedOutput implements TypedOutput {
        private final byte[] jsonBytes;
        private final String mimeType;

        JsonTypedOutput(byte[] jsonBytes, String encode) {
            this.jsonBytes = jsonBytes;
            this.mimeType = "application/json; charset=" + encode;
        }

        @Override public String fileName() {
            return null;
        }

        @Override public String mimeType() {
            return mimeType;
        }

        @Override public long length() {
            return jsonBytes.length;
        }

        @Override public void writeTo(OutputStream out) throws IOException {
            out.write(jsonBytes);
        }
    }
}
